#include<bits/stdc++.h>


template<class T>
struct Fen {
    int n;
    vector<T> t;
    Fen (int n_) {
        init(n_);
    }
    Fen () {};
    void init(int n_) {
        n = n_;
        t.assign(n + 1, {});
    }
    void change(int u, T x) {
        for(; u <= n; u += u & -u) t[u] += x;
    }
    T sum(int u) {
        T res = 0;
        for(; u; u -= u & -u) res += t[u];
        return res;
    }
    T sum(int l, int r) {
        return sum(r) - sum(l - 1);
    }

    int kth(T sum) {
        int i = 0;
        T tot = {};
        for (int j = 1 << __lg(n); j > 0; j /= 2) {
            if (i + j <= n && t[i + j] + tot < sum) {
                i += j;
                tot += t[i];
            }
        }
        return i + 1;
    }
};

#include<bits/extc++.h>
// using namespace __gnu_cxx;
using namespace __gnu_pbds;
using namespace std;
#define ll long long 
#define pii pair<int, int>

tree<pii, null_type, less<pii>, rb_tree_tag, tree_order_statistics_node_update> t;
//25
void solve() {
    int n;
    cin >> n;

    for (int i = 1; i <= n; i++) {
        int opt, x;
        cin >> opt >> x;
        if (opt == 1) {
            // 插入
            t.insert((pii){x, i});
        } else if (opt == 2) {
            // 删除
            t.erase(t.lower_bound({x, 0}));
        } else if (opt == 3) {
            // 排名
            cout << t.order_of_key({x, 0}) + 1 << '\n';
        } else if (opt == 4) {
            // 排名为x的数
            cout << t.find_by_order(x - 1)->first << '\n';
        } else if (opt == 5) {
            // 前驱
            auto it = t.lower_bound({x, 0});
            it--;
            cout << it->first << '\n';
        } else if (opt == 6) {
            // 后继
            cout << t.lower_bound({x + 1, 0})->first << '\n';
        }
    }
}

template<class Info, class Tag>
struct Segment {
	int n;
	vector<Info> info;
	vector<Tag> tag;
	Segment(int n_, vector<Info> & init) {
		n = n_; info.resize(n * 4 + 10), tag.resize(n * 4 + 10);
		build(1, 1, n, init);
	}
    Segment(int n_) {
        n = n_;
        info.assign(n * 4 + 10, {}), tag.assign(n * 4 + 10, {});
    }
	void build(int u, int l, int r, vector<Info> &init) {
		if(l == r) {info[u] = init[l]; return;}
		int mid = l + r >> 1;
		build(u * 2, l, mid, init); build(u * 2 + 1, mid + 1, r, init);
		info[u] = info[u * 2] + info[u * 2 + 1];
	}
	Info query(int u, int l, int r, int ul, int ur) {
		if(l <= ul && r >= ur) return info[u];
		int mid = ul + ur >> 1;
		push_down(u);
		if(r <= mid) return query(u * 2, l, r, ul, mid);
		if(l > mid) return query(u * 2 + 1, l, r, mid + 1, ur);
		return query(u * 2, l, r, ul, mid) + query(u * 2 + 1, l, r, mid + 1, ur);
	}
	Info query(int l, int r) {
		return query(1, l, r, 1, n);
	}
	void push(int v,const Tag & t) {
		tag[v].aply(t); 
		info[v].aply(t);
	}
	void push_down(int u) {
		push(u * 2, tag[u]); push(u * 2 + 1, tag[u]);
		tag[u] = Tag();
	}
	void change(int u, int l, int r, const Tag& x, int ul, int ur) {
		if(l <= ul && r >= ur) {
			push(u, x);
			return;
		}
		int mid = ul + ur >> 1;
		push_down(u);
		if(l <= mid) change(u * 2, l, r, x, ul, mid);
		if(r > mid) change(u * 2 + 1, l, r, x, mid + 1, ur);
		info[u]	= info[u * 2] + info[u * 2 + 1];
	}
	void change(int l, int r, const Tag& x) {
		change(1, l, r, x, 1, n);
	}
};


/*
单点修改 区间合并 线段树 区间 1 - n
注意 change里面的单点修改的逻辑要注意，是+还是覆盖
注意 pred传一个谓词，返回1代表答案在此区间。注意逻辑，可能需要外部变量辅助。
*/
template <class Info>
struct Segtree{
    int n;  
    vector<Info> info;
    Segtree(int n_, Info info = Info()) {
        init(vector<Info>(n_ + 1, info));
    }
    Segtree() : n(0) {}
    void init(const vector<Info> &init) {
        n = (int)init.size() - 1;
        info.assign(4 * n + 2, Info{});
        build(1, 1, n, init);
    }
    void build(int u, int l, int r, const vector<Info> &init) {
        if(l == r) {
            info[u] = init[l];
            return;
        }
        int mid = l + r >> 1;
        build(u * 2, l, mid, init); build(u * 2 + 1, mid + 1, r, init);
        info[u] = info[u * 2] + info[u * 2 + 1];
    }
    void change(int u, int p, const Info & x, int ul, int ur) {
        if(ul == ur) {
            info[u] = x; // todo
            return;
        }
        int mid = ul + ur >> 1;
        if(p <= mid) change(u * 2, p, x, ul, mid);
        else change(u * 2 + 1, p, x, mid + 1, ur);
        info[u] = info[u * 2] + info[u * 2 + 1];
    }
    void change(int p, const Info & x) {
        change(1, p, x, 1, n);
    }
    Info query(int u, int l, int r, int ul, int ur) {
        if(l <= ul && r >= ur) {
            return info[u];
        }
        int mid = ul + ur >> 1;
        if(r <= mid) return query(u * 2, l, r, ul, mid);
        if(l > mid) return query(u * 2 + 1, l, r, mid + 1, ur);
        return query(u * 2, l, r, ul, mid) + query(u * 2 + 1, l, r, mid + 1, ur);
    }
    Info query(int l, int r) {
        return query(1, l, r, 1, n);
    }
    template<class F>
    int findFirst(int u, int l, int r, int ul, int ur, F &&pred) {
        if (r < ul || ur < l) return -1;
        if (l <= ul && ur <= r && !pred(info[u])) return -1;
        if (ul == ur) return ul;
        int mid = ul + ur >> 1;
        int res = findFirst(u * 2, l, r, ul, mid, pred);
        if (res == -1) res = findFirst(u * 2 + 1, l, r, mid + 1, ur, pred);
        return res;
    };  
    // 找到第一个满足pred的前缀，如果找不到，返回-1
    template<class F>
    int findFirst(int l, int r, F &&pred) {
        return findFirst(1, l, r, 1, n, pred);
    }
};


struct St {
    int n, m;
    vector<vector<int>> st;
    St(vector<int> a) {
        n = a.size();
        m = __lg(n);
        st.assign(m + 1, vector<int> (n + 1, 0));
        for (int i = 0; i < n; i++) st[0][i] = a[i];
        for (int j = 1; j <= m; j++) for (int i = 0; i < n; i++) {
            if (i + (1 << j - 1) >= n) break;
            st[j][i] = max(st[j - 1][i], st[j - 1][i + (1 << j - 1)]);
        }
    }
    int get(int l, int r) {
        int j = __lg(r - l + 1);
        return max(st[j][l], st[j][r - (1 << j) + 1]);
    }
};

// 矩形面积并（离散化，输入的为点）
struct line {
    int x0, x1, y, tag;
    bool operator<(const line& a) const {
        return y == a.y ? tag > a.tag: y < a.y;
    }
};

// b 是离散化数组，下标从1开始有效
vector<int> b;
struct Tr {
    struct nd {
        int cnt, len;
    };
    vector<nd> t;
    int n;
    Tr (int n_) {
        n = n_;
        t.assign(n * 4, {});
    }
    void change(int u, int l, int r, int x, int ul, int ur) {
        if (l > ur || r < ul) return;
        if (l <= ul && r >= ur) {
            t[u].cnt += x;
        } else {
            int mid = ul + ur >> 1;
            if (ul ^ ur) {
                change(u * 2, l, r, x, ul, mid);
                change(u * 2 + 1, l, r, x, mid + 1, ur);
            }
        }
        if (t[u].cnt) t[u].len = b[ur + 1] - b[ul];
        else if (ul != ur) t[u].len = t[u * 2].len + t[u * 2 + 1].len;
        else t[u].len = 0;
    }
    void change(int l, int r, int x) {
        change(1, l, r, x, 1, n);
    }
    int get() {
        return t[1].len;
    }
};

// 矩形面积并，1-n不离散化，格点表示
struct Tr {
    struct nd{
        int cnt, len;
    };
    vector<nd> t;
    int n;
    Tr(int n_) {
        n = n_;
        t.assign(n * 4, {});
    }
    void change(int l, int r, int x) {
        change(1, l, r, x, 1, n);
    }
    void change(int u, int l, int r, int x, int ul, int ur) {
        if (l > ur || r < ul) return;
        if (l <= ul && r >= ur) {
            t[u].cnt += x;
        } else {
            int mid = ul + ur >> 1;
            if (ul ^ ur) {
                change(u * 2, l, r, x, ul, mid);
                change(1 + u * 2, l, r, x, mid + 1, ur);
            }
        }
        if (t[u].cnt) t[u].len = ur - ul + 1;
        else t[u].len = ul == ur ? 0 : t[u * 2].len + t[u * 2 + 1].len;
    }
    int get() {
        return t[1].len;
    }
};




// 线段树合并
template<class Info>
struct Tr {
    vector<int> ls, rs;
    
    vector<Info> t;
    int n, tot;
    Tr (int n_, int m) : n(n_) {
        tot = 0;
        t.assign(m, {});
        ls.assign(m, {});
        rs.assign(m, {});
    }

    void change(int &u, int p, const Info& info, int l, int r) {
        if (!u) u = ++tot;
        if (l == r) {
            t[u].modify(info);
            return;
        }
        int mid = l + r >> 1;
        if (p <= mid) change(ls[u], p, info, l, mid);
        else change(rs[u], p, info, mid + 1, r);
        t[u] = t[ls[u]] + t[rs[u]];
    }
    void change(int &u, int p, const Info& info) {
        change(u, p, info, 1, n);
    }
    int merge(int u, int v) {
        return merge(u, v, 1, n);
    }
    int merge(int u, int v, int l, int r) {
        if (!u || !v) return u + v;
        if (l == r) {
            t[u].modify(t[v]);
            return u;
        }
        int mid = l + r >> 1;
        ls[u] = merge(ls[u], ls[v], l, mid);
        rs[u] = merge(rs[u], rs[v], mid + 1, r);
        t[u] = t[ls[u]] + t[rs[u]];
        return u;
    }
    Info query(int u, int l, int r) {
        return query(u, l, r, 1, n);
    }
    Info query(int u, int l, int r, int ul, int ur) {
        if (l <= ul && r >= ur) return t[u];
        int mid = ul + ur >> 1;
        if (r <= mid) return query(ls[u], l, r, ul, mid);
        if (l > mid) return query(rs[u], l, r, mid + 1, ur);
        return query(ls[u], l, r, ul, mid) + query(rs[u], l, r, mid + 1, ur);
    }

    int find(int u, ll k, int l, int r) {
        if (t[u].sum < k) return -1;
        if (l == r) {
            return l;
        }
        int mid = l + r >> 1;
        ll suml = t[ls[u]].sum;
        if (suml >= k) return find(ls[u], k, l, mid);
        else return find(rs[u], k - suml, mid + 1, r);
    }
    int find(int u, ll k) {
        return find(u, k, 1, n);
    }

    void split(int &u, int &v, int l, int r) {
        split(u, v, l, r, 1, n);
    }
    void split(int &u, int &v, int l, int r, int ul, int ur) {
        if (r < ul || l > ur || !u) return;
        if (l <= ul && r >= ur) {
            v = u;
            u = 0;
            return;
        }
        int mid = ul + ur >> 1;
        v = ++tot;
        split(ls[u], ls[v], l, r, ul, mid);
        split(rs[u], rs[v], l, r, mid + 1, ur);
        t[u] = t[ls[u]] + t[rs[u]];
        t[v] = t[ls[v]] + t[rs[v]];
    }
};
struct Info {
    ll sum;
    // push_up函数
    Info operator+(const Info& t) const {
        return {sum + t.sum};
    }
    // 单点修改逻辑，其中change和merge的叶子节点需要用到。
    void modify(const Info& t) {
        sum += t.sum;
    }
};



struct Splay {
    #define ls(x) t[x].s[0]
    #define rs(x) t[x].s[1]
    #define fa(x) t[x].f
    #define notrt(x) (ls(fa(x)) == x || rs(fa(x)) == x)
    struct nd {
        int s[2], f, v, sz;
        // todo
    };
    vector<nd> t;
    int rt, tot;
    Splay() {
        rt = tot = 0;
        t.push_back({});
    }
    void push_up(int x) {
        t[x].sz = 1 + t[ls(x)].sz + t[rs(x)].sz;
        // todo
    }
    void rotate(int x) {
        int y = fa(x), z = fa(y);
        if (notrt(y)) t[z].s[rs(z) == y] = x;
        fa(x) = z;
        int r = rs(y) == x;
        t[y].s[r] = t[x].s[r ^ 1];
        fa(t[y].s[r]) = y;
        t[x].s[r ^ 1] = y;
        fa(y) = x;
        push_up(y), push_up(x);
    }
    void splay(int x, int f) {
        while (fa(x) != f) {
            int y = fa(x), z = fa(y);
            if (z ^ f) rotate((rs(z) == y) ^ (rs(y) == x) ? x : y);
            rotate(x);
        }
        if (f == 0) rt = x;
    }
    void push_down(int x) {
        // todo
    }
};




struct Lct {
    #define ls(x) t[x].s[0]
    #define rs(x) t[x].s[1]
    #define fa(x) t[x].f
    #define notrt(x) (ls(fa(x)) == x || rs(fa(x)) == x)
    
    void rotate(int x) {
        int y = fa(x), z = fa(y);
        if (notrt(y)) t[z].s[rs(z) == y] = x;
        fa(x) = z;
        int r = rs(y) == x;
        t[y].s[r] = t[x].s[r ^ 1];
        fa(t[y].s[r]) = y;
        t[x].s[r ^ 1] = y;
        fa(y) = x;
        push_up(y), push_up(x);
    }
    void splay(int x) {
        push_all(x);
        while (notrt(x)) {
            int y = fa(x), z = fa(y);
            if (notrt(y)) rotate((rs(z) == y) ^ (rs(y) == x) ? x : y);
            rotate(x);
        }
    }
    void push_all(int x) {
        if (notrt(x)) push_all(fa(x));
        push_down(x);
    }
    
    void makert(int x) {
        access(x);
        splay(x);
        t[x].tag ^= 1;
    }
    // x作为原树的根，y作为辅助树的根
    void getChain(int x, int y) {
        makert(x), access(y), splay(y);
    }
    int show(int x, int y) {
        getChain(x, y);
        return t[y].sum;
    }
    // 得到x的原树的根，并把这个根转到辅助树的根
    int getrt(int x) {
        access(x); splay(x);
        while (1) {
            push_down(x);
            if (ls(x)) x = ls(x);
            else break;
        }
        splay(x);
        return x;
    }
    void link(int x, int y) {
        makert(x);
        if (getrt(y) != x) fa(x) = y;
    }
    void cut(int x, int y) {
        makert(x);
        if (getrt(y) == x && fa(y) == x && !ls(y)) {
            fa(y) = rs(x) = 0; push_up(x);
        }
    }
    void change(int x, int y) {
        splay(x);
        t[x].v = y;
        push_up(x);
    }
    int lca(int x, int y) {
        access(y);
        int ans = x;
        for (int y = 0; x; y = x, x = fa(x)) {
            splay(x);
            rs(x) = y;
            push_up(x);
            ans = x;
        }
        return ans;
    }
    void access(int x) {
        for (int y = 0; x; y = x, x = fa(x)) {
            splay(x);
            rs(x) = y;
            push_up(x);
        }
    }

    struct nd {
        int s[2], f, v, sz;
        // todo
        int tag, sum;
    };
    int tot, n;
    vector<nd> t;
    // todo 构造函数
    Lct(int n_, vector<int> a) {
        n = n_;
        t.assign(n + 1, {});
        for (int i = 1; i <= n; i++) {
            t[i].v = t[i].sum = a[i];
        }
    }
    // 手动改变ls，rs，v等信息时需要pushup
    void push_up(int x) {
        t[x].sz = 1 + t[ls(x)].sz + t[rs(x)].sz;
        // todo
        t[x].sum = t[x].v ^ t[ls(x)].sum ^ t[rs(x)].sum;
    }
    void push_down(int x) {
        // todo
        if (t[x].tag) {
            t[ls(x)].tag ^= 1;
            t[rs(x)].tag ^= 1;
            swap(ls(x), rs(x));
            t[x].tag = 0;
        }
    }
};


/*
左偏树、可并堆合并操作。
*/
vector<int> v(n + 1), l(n + 1), r(n + 1), d(n + 1), del(n + 1);
d[0] = -1;
for (int i = 1; i <= n; i++) cin >> v[i];
function<int(int, int)> merge = [&] (int x, int y) {
    if (!x || !y) return x + y;
    if ((v[x] == v[y] && x > y) || (v[x] > v[y])) swap(x, y);
    r[x] = merge(r[x], y);
    d[x] = d[r[x]] + 1;
    if (d[l[x]] < d[r[x]]) swap(l[x], r[x]);
    return x;
};


/*
fhqtreap
*/
mt19937 rd(time(0));
int gen(int l, int r) {return rd() % (r - l + 1) + l;}
#define getsz(x) (x ? x->sz : 0)
#define getv(x) (x ? x->v : 0)
// todo
struct Node {
    Node* l,* r;
    int pri, v, sz;
    bool rev;
    Node(int v_ = 0) {
        l = r = NULL;
        pri = gen(0, 1e7), sz = 1, v = v_, rev = 0;
    }    
    // Info todo

    void push_up() {
        sz = getsz(l) + getsz(r) + 1;
        // todo
    }
    void push_down() {
        // todo
        if (rev) {
            swap(l, r);
            if (l) l->rev ^= 1;
            if (r) r->rev ^= 1;
            rev = 0;
        }
    }
};

// k num give u
void split(Node* x, Node*& u, Node*& v, int k) {
    if (x == NULL) {
        u = v = NULL; return;
    }
    x->push_down();
    if (getsz(x->l) + 1 <= k) {
        u = x;
        split(x->r, u->r, v, k - getsz(x->l) - 1);
        u->push_up();
    } else {
        v = x;
        split(x->l, u, v->l, k);
        v->push_up();
    }
}
// allv(u) <= allv(v)
Node* merge(Node* u, Node* v) {
    if (!u) return v; if (!v) return u;
    if (u->pri < v->pri) {
        u->push_down();
        u->r = merge(u->r, v);
        u->push_up();
        return u;
    } else {
        v->push_down();
        v->l = merge(u, v->l);
        v->push_up();
        return v;
    }
}